package dao

import (
	"context"
	"errors"

	"bilinadmin/pkg/db/pgex"

	"bilinadmin/internal/model"
)

// InventoryDao 仓库相关
type InventoryDao interface {
	// CreateInventory 创建仓库
	CreateInventory(ctx context.Context, inv *model.Inventory) error
	// UpdateInventory 更新仓库
	UpdateInventory(ctx context.Context, inv *model.Inventory) error
	// LockInventoryById 锁定仓库
	LockInventoryById(ctx context.Context, id int64) (*model.Inventory, error)
	// GetInventoryById 获取仓库
	GetInventoryById(ctx context.Context, id int64) (*model.Inventory, error)
	// GetInventoriesByBrandStore 根据品牌门店获取仓库
	GetInventoriesByBrandStore(ctx context.Context, brandId, storeId int64) ([]*model.Inventory, error)
}

var invDao InventoryDao

type invDaoImpl struct {
	*DaoBase
	name string
}

// InitInventoryDao 初始化 dao
func InitInventoryDao() {
	invDao = &invDaoImpl{
		DaoBase: daoBase,
		name:    "inventory_dao",
	}
}

// GetInventoryDao 获取 dao
func GetInventoryDao() InventoryDao {
	return invDao
}

// CreateInventory 创建仓库
func (dao *invDaoImpl) CreateInventory(ctx context.Context, inv *model.Inventory) error {
	if inv == nil {
		return nil
	}
	param := []interface{}{
		inv.Id,
		inv.BrandId,
		inv.StoreId,
		inv.Name,
		inv.ContactName,
		inv.ContactMobile,
		inv.CityCode,
		inv.RegionCode,
		inv.Address,
		inv.Latitude,
		inv.Longitude,
		inv.Status,
		inv.ModifyEmpId,
		inv.CreatedAt,
		inv.UpdatedAt,
	}
	query := "INSERT INTO inventory (id, brand_id, store_id, name, contact_name, contact_mobile, city_code, region_code, " +
		"address, latitude, longitude, status, modify_emp_id, created_at, updated_at) " +
		"VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"
	_, err := dao.db.Insert(ctx, query, param...)
	return err
}

// UpdateInventory 更新仓库
func (dao *invDaoImpl) UpdateInventory(ctx context.Context, inv *model.Inventory) error {
	if inv == nil {
		return nil
	}
	param := []interface{}{
		inv.Name,
		inv.ContactName,
		inv.ContactMobile,
		inv.CityCode,
		inv.RegionCode,
		inv.Address,
		inv.Latitude,
		inv.Longitude,
		inv.Status,
		inv.ModifyEmpId,
		inv.UpdatedAt,
		inv.Id,
	}
	query := "UPDATE inventory SET name=?, contact_name=?, contact_mobile=?, city_code=?, region_code=?, address=?, " +
		"latitude=?, longitude=?, status=?, modify_emp_id=?, updated_at=? WHERE id=? AND deleted_at=0"
	_, err := dao.db.Update(ctx, query, param...)
	return err
}

// LockInventoryById 锁定仓库
func (dao *invDaoImpl) LockInventoryById(ctx context.Context, id int64) (*model.Inventory, error) {
	err := dao.needTrans(ctx)
	if err != nil {
		return nil, err
	}
	query := "SELECT * FROM inventory WHERE id=? AND deleted_at=0 FOR UPDATE"
	inv := &model.Inventory{}
	err = dao.db.Get(ctx, inv, query, id)
	if err != nil && errors.Is(err, pgex.ErrEmpty) {
		return nil, nil
	}
	return inv, err
}

// GetInventoryById 获取仓库
func (dao *invDaoImpl) GetInventoryById(ctx context.Context, id int64) (*model.Inventory, error) {
	query := "SELECT * FROM inventory WHERE id=? AND deleted_at=0 FOR UPDATE"
	inv := &model.Inventory{}
	err := dao.db.Get(ctx, inv, query, id)
	if err != nil && errors.Is(err, pgex.ErrEmpty) {
		return nil, nil
	}
	return inv, err
}

// GetInventoriesByBrandStore 根据品牌门店获取仓库
func (dao *invDaoImpl) GetInventoriesByBrandStore(ctx context.Context, brandId, storeId int64) ([]*model.Inventory, error) {
	query := "SELECT id, brand_id, store_id, name FROM inventory WHERE brand_id=? AND store_id=? AND deleted_at=0"
	var invs []*model.Inventory
	err := dao.db.Query(ctx, &invs, query, brandId, storeId)
	return invs, err
}
